﻿using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Text.Json;
using System.Threading.Tasks;

namespace xycn.common
{
    /// <summary>
    /// ConvertExtension
    /// </summary>	
    public static class ConvertExtension
    {
        /// <summary>
        /// The convert helper.
        /// </summary>
        /// <param name="value">
        /// The value.
        /// </param>
        /// <param name="conversionType">
        /// The conversion type.
        /// </param>
        /// <returns>
        /// The <see cref="object"/>.
        /// </returns>
        public static object ConvertHelper(object value, Type conversionType)
        {
            Type nullableType = Nullable.GetUnderlyingType(conversionType);

            // 判断当前类型是否可为 null
            if (nullableType != null)
            {
                if (value == DBNull.Value)
                {
                    return null;
                }

                // 若是枚举 则先转换为枚举
                if (nullableType.IsEnum)
                {
                    value = System.Enum.Parse(nullableType, value.ToString());
                }

                return Convert.ChangeType(value, nullableType);
            }

            if (conversionType.IsEnum)
            {
                return System.Enum.Parse(conversionType, value.ToString());
            }

            if (conversionType.Name.ToLower() == "datetime" && value.GetType().Name.ToLower() == "mysqldatetime" && value.ToString().StartsWith("0000-00-00"))
            {
                return new DateTime(1970, 1, 1);
            }

            return Convert.ChangeType(value, conversionType);
        }

        /// <summary>
        /// The convert to decimal null.
        /// </summary>
        /// <param name="targetObj">
        /// The target obj.
        /// </param>
        /// <returns>
        /// The <see cref="decimal"/>.
        /// </returns>
        public static decimal? ConvertToDecimalNull(object targetObj)
        {
            if (targetObj == null || targetObj == DBNull.Value)
            {
                return null;
            }

            return Convert.ToDecimal(targetObj);
        }

        /// <summary>
        /// The convert to int null.
        /// </summary>
        /// <param name="targetObj">
        /// The target obj.
        /// </param>
        /// <returns>
        /// The <see cref="int"/>.
        /// </returns>
        public static int? ConvertToIntNull(object targetObj)
        {
            if (targetObj == null || targetObj == DBNull.Value)
            {
                return null;
            }

            return Convert.ToInt32(targetObj);
        }
        /// <summary>
        /// toint 返回0或int值
        /// </summary>
        /// <param name="value"></param>
        /// <returns></returns>
        public static int Toint(this object value)
        {
            try
            {
                if (value == null || value == DBNull.Value)
                {
                    return 0;
                }
                else
                {
                    return Convert.ToInt32(value);
                }
            }
            catch (Exception)
            {
                return 0;
            }
        }

        /// <summary>
        /// The convert to string.
        /// </summary>
        /// <param name="obj">
        /// The obj.
        /// </param>
        /// <returns>
        /// The <see cref="string"/>.
        /// </returns>
        public static string ConvertToString(object obj)
        {
            return obj == null ? string.Empty : obj.ToString();
        }

        /// <summary>
        /// 将泛类型集合List类转换成DataTable
        /// </summary>
        /// <param name="entitys">泛类型集合</param>
        /// <typeparam name="T">T</typeparam>
        /// <returns>DataTable</returns>
        public static DataTable ListToDataTable<T>(List<T> entitys)
        {
            // 检查实体集合不能为空
            if (entitys == null || entitys.Count < 1)
            {
                throw new Exception("需转换的集合为空");
            }

            // 取出第一个实体的所有Propertie
            Type entityType = entitys[0].GetType();
            PropertyInfo[] entityProperties = entityType.GetProperties();

            // 生成DataTable的structure
            // 生产代码中，应将生成的DataTable结构Cache起来，此处略
            DataTable dt = new DataTable();
            foreach (PropertyInfo t in entityProperties)
            {
                // dt.Columns.Add(entityProperties[i].Name, entityProperties[i].PropertyType);
                dt.Columns.Add(t.Name);
            }

            // 将所有entity添加到DataTable中
            foreach (object entity in entitys)
            {
                // 检查所有的的实体都为同一类型
                if (entity.GetType() != entityType)
                {
                    throw new Exception("要转换的集合元素类型不一致");
                }

                object[] entityValues = new object[entityProperties.Length];
                for (int i = 0; i < entityProperties.Length; i++)
                {
                    entityValues[i] = entityProperties[i].GetValue(entity, null);
                }

                dt.Rows.Add(entityValues);
            }

            return dt;
        }


        /// <summary>
        /// 将字典类型序列化为json字符串
        /// </summary>
        /// <typeparam name="TKey">字典key</typeparam>
        /// <typeparam name="TValue">字典value</typeparam>
        /// <param name="dict">要序列化的字典数据</param>
        /// <returns>json字符串</returns>
        public static string DicToJson<TKey, TValue>(Dictionary<TKey, TValue> dict)
        {
            if (dict.Count == 0)
                return "";

            string jsonStr = JsonSerializer.Serialize(dict);
            return jsonStr;
        }

        /// <summary>
        /// 将json字符串反序列化为字典类型 Key保持原样 不做转换
        /// </summary>
        /// <typeparam name="TKey">字典key</typeparam>
        /// <typeparam name="TValue">字典value</typeparam>
        /// <param name="jsonStr">json字符串</param>
        /// <returns>字典数据</returns>
        public static Dictionary<TKey, TValue> JsonToDic<TKey, TValue>(string jsonStr)
        {
            if (string.IsNullOrEmpty(jsonStr))
                return new Dictionary<TKey, TValue>();

            Dictionary<TKey, TValue> jsonDict = JsonSerializer.Deserialize<Dictionary<TKey, TValue>>(jsonStr);

            return jsonDict;

        }

        /// <summary>
        /// 将json字符串反序列化为字典类型 Key保持原样 不做转换
        /// </summary>
        /// <param name="jsonStr">json字符串</param>
        /// <returns>字典数据</returns>
        public static Dictionary<string, object> JsonToDic(string jsonStr)
        {
            return JsonToDic<string, object>(jsonStr);
        }

        /// <summary>
        /// 将json字符串反序列化为字典类型 Key小写
        /// </summary>
        /// <param name="jsonStr">json字符串</param>
        /// <returns>字典数据</returns>
        public static Dictionary<string, object> JsonToDicWithKeyToLower(string jsonStr)
        {
            var ret = new Dictionary<string, object>();

            foreach (var item in JsonToDic<string, object>(jsonStr))
            {
                ret.Add(item.Key.ToLower(), item.Value);
            }
            return ret;
        }

        /// <summary>
        /// The convert to string.
        /// </summary>
        /// <param name="obj">The obj.</param>
        /// <returns>The <see cref="string" />.</returns>
        public static bool ConvertToBool(object obj)
        {
            if (obj == null)
            {
                return false;
            }
            else if (obj.ToString().Length == 0)
            {
                return false;
            }
            else if (obj.ToString() == "1")
            {
                return true;
            }
            else if (obj.ToString().ToLower() == "true")
            {
                return true;
            }
            return false;
        }
    }
}
